<template>
	<!--撑开上级容器的宽高-->
	<div class='calendar-container' :style='{fontSize:fontSize}'>
		<!--当前年月-->
		<div class='header'>
			<div>
				{{ titleText }}
			</div>
			<div>
				其他内容
			</div>
		</div>
		<!--周-->
		<div class='weeks'>
			<div class='week'>周一</div>
			<div class='week'>周二</div>
			<div class='week'>周三</div>
			<div class='week'>周四</div>
			<div class='week'>周五</div>
			<div class='week'>周六</div>
			<div class='week'>周日</div>
		</div>
		<!--日-->
		<div class='days'>
			<template v-for='(item) of dayList' :key='`${item["dateStr"]}`'>
				<div :class='{"cell":true,"selected":item["isSelected"],"otherMonth":item["isOtherMonth"]}'
					 @click='(event:Event)=>onDateClick(event,item)'>
					<!--日期-->
					<template v-if='item["isToday"]'>
						<div class='today'>{{ item['day'] }}</div>
					</template>
					<template v-else>
						<div>{{ item['day'] }}</div>
					</template>
					<!--年月日-->
					<div>{{ item['dateStr'] }}</div>
					<!--农历/阴历-->
					<div class='other-calendar'>
						<div>{{ item['chineseStr'] }}</div>
						<div>{{ item['lunarStr'] }}</div>
					</div>
					<!--日程-->
					<div>{{ item['memoStr'] }}</div>
					<!--下划线-->
					<div class='cell-bottom'></div>
				</div>
			</template>
		</div>
	</div>
</template>
<script setup lang='ts'>
import { onBeforeMount, ref } from 'vue';
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
import 'dayjs/locale/zh-cn.js';
import type { CalendarData } from '@/components/ui/calendar/Calendar.d.ts';
const titleText = ref<string>();
const dayList = ref<Array<CalendarData>>([]);
const props = defineProps({
	// 字体大小
	fontSize : {
		type    : String,
		require : false,
		default : '1rem'
	},
	// 手风琴模式
	accordion : {
		type    : Boolean,
		require : false,
		default : false
	},
	// 能否取消选择
	cancel : {
		type    : Boolean,
		require : false,
		default : false
	},
	// 鼠标左键单击日历事件
	onDateClick : {
		type    : Function,
		require : false,
		default : undefined
	}
});
onBeforeMount(() => {
	// 默认是当前年月的日历
	initCalendar(dayjs());
	// 测试其他年月
	// initCalendar('2022-11');
	// 测试不规范年月
	// initCalendar('2022-1111');
});
const initCalendar = async (yearMonth: string | dayjs.Dayjs): Promise<void> => {
	// 清掉缓存
	dayList.value = [];
	dayjs.locale('zh-cn');
	dayjs.extend(customParseFormat);
	// 获取当前年月日
	let currentDate;
	// 判断是否是dayJs对象
	if (dayjs.isDayjs(yearMonth)) {
		// 是则直接使用
		currentDate = yearMonth;
	} else {
		// 否则转换一下再用
		// 校验下日期,符合格式则转换
		if (dayjs(yearMonth, [
			'YYYY-MM',
			'YYYY年MM月',
			'YYYY年MM',
			'YYYY MM',
			'YYYY/MM'
		], true).isValid()) {
			currentDate = dayjs(yearMonth, [
				'YYYY-MM',
				'YYYY年MM月',
				'YYYY年MM',
				'YYYY MM',
				'YYYY/MM'
			]);
		} else {
			// 否则直接用当前年月
			console.warn('你输入的年月不符合格式,将以当前年月来显示');
			currentDate = dayjs();
		}
	}
	// 展示当前年月日
	titleText.value = currentDate.format('YYYY-MM');
	// 本月第一天
	const currentMonthStartDay = currentDate.startOf('month');
	console.log(`本月第一天是${currentMonthStartDay.format('YYYY-MM-DD')}`);
	// 本月最后一天
	const currentMonthEndDay = currentDate.endOf('month');
	// 本月最后一天数字
	const currentMonthEndDayNumber = currentMonthEndDay.date();
	// 本月第一天是周几
	const currentMonthStartDayWeekDay = currentMonthStartDay.day();
	console.log(`本月第一天是周${currentMonthStartDayWeekDay}`);
	// 在数组的开头添加上月的数天,补满一周7天
	for (let i = (currentMonthStartDayWeekDay - 1); 1 <= i; i--) {
		const operatedDate = currentMonthStartDay.subtract(i, 'day');
		const dateStr = operatedDate.format('YYYY-MM-DD') as string;
		dayList.value.push(await calcCalendar(currentDate, operatedDate, dateStr));
	}
	// 添加本月日期
	for (let j = 0; j < currentMonthEndDayNumber; j++) {
		let operatedDate = currentMonthStartDay.add(j, 'day');
		const dateStr = operatedDate.format('YYYY-MM-DD') as string;
		dayList.value.push(await calcCalendar(currentDate, operatedDate, dateStr));
	}
	// 检查本月最后一天是周几
	const currentMonthEndDayWeekDay = currentMonthEndDay.day();
	console.log(`本月最后一天是周${currentMonthEndDayWeekDay}`);
	// 追加下个月的开头数天,补满(本月最后一周缺的天数+7)
	for (let k = 1; k <= (7 - currentMonthEndDayWeekDay + 7); k++) {
		let operatedDate = currentDate.endOf('month').add(k, 'day') as dayjs.Dayjs;
		const dateStr = operatedDate.format('YYYY-MM-DD') as string;
		dayList.value.push(await calcCalendar(currentDate, operatedDate, dateStr));
	}
};
const calcCalendar = async (currentYearMonth: dayjs.Dayjs, operatedDate: dayjs.Dayjs,
	dateStr: string): Promise<CalendarData> => {
	return {
		year  : operatedDate.year(),
		month : operatedDate.month() + 1,
		day   : operatedDate.date(),
		// TODO 计算农历(二十四节气历)
		chineseStr : '我是农历',
		// TODO 计算阴历(月亮历)
		lunarStr     : '我是阴历',
		dateStr      : dateStr,
		memoStr      : '我是日程',
		isSelected   : false,
		isOtherMonth : !currentYearMonth.isSame(operatedDate, 'month'),
		isToday      : dayjs().isSame(operatedDate, 'date')
	};
};
const onDateClick = async (event: Event, row: CalendarData): Promise<void> => {
	// 判断是否存在onDateClick方法,不存在则不尝试执行
	if (props.onDateClick) {
		props.onDateClick(event, row);
	}
	// 手风琴模式需要清除其他的日历选中状态
	console.log(row['isSelected']);
	if (props.accordion) {
		await handleAccordion(row);
	} else {
		await handleCancel(row);
	}
};
const handleAccordion = async (row: CalendarData) => {
	let newRow;
	dayList.value.forEach((item: CalendarData) => {
		item['isSelected'] = false;
		if (item.dateStr === row.dateStr) {
			handleCancel(item);
		}
	});
};
const handleCancel = async (row: CalendarData) => {
	if (props.cancel) {
		console.log(row['isSelected']);
		row['isSelected'] = !row['isSelected'];
	} else {
		row['isSelected'] = true;
	}
};
</script>
<style scoped lang='scss'>
.calendar-container{
	box-sizing      :border-box;
	margin          :0;
	padding         :0;
	border          :none;
	height          :100%;
	/*width           :100%;*/
	// min-width  :calc(80px * 7);
	overflow        :auto;
	display         :flex;
	flex-direction  :column;
	flex-wrap       :nowrap;
	align-content   :center;
	justify-content :center;
	align-items     :center;
	.header{
		box-sizing      :border-box;
		margin          :0;
		padding         :0;
		border          :1px solid rgba(239, 239, 245, 1);
		width           :100%;
		height          :calc(100% / 8);
		font-size       :1.2em;
		display         :flex;
		flex-direction  :row;
		flex-wrap       :nowrap;
		align-content   :center;
		justify-content :space-evenly;
		align-items     :center;
	}
	.weeks{
		box-sizing            :border-box;
		margin                :0;
		padding               :0;
		border                :none;
		width                 :100%;
		height                :calc(100% / 8);
		font-size             :.9em;
		display               :grid;
		// gap                   :10px 10px;
		grid-template-columns : repeat(7, minmax(80px, 1fr));
		align-content         :stretch;
		justify-content       :start;
		align-items           :center;
		justify-items         :center;
		.week{
			box-sizing      :border-box;
			margin          :0;
			padding         :0;
			border          :1px solid rgb(239, 239, 245);
			width           :100%;
			height          :100%;
			display         :flex;
			flex-direction  :row;
			flex-wrap       :nowrap;
			align-content   :center;
			justify-content :center;
			align-items     :center;
		}
		.week + .week{
			margin :0 -1px;
		}
	}
	.days{
		box-sizing            :border-box;
		margin                :0;
		padding               :0;
		border                :none;
		width                 :100%;
		height                :calc(100% / 8 * 6);
		font-size             :.9em;
		cursor                :pointer;
		display               :grid;
		// gap                   :10px 10px;
		grid-template-columns : repeat(7, minmax(80px, 1fr));
		grid-template-rows    : repeat(6, 1fr);
		align-content         :stretch;
		justify-content       :start;
		align-items           :center;
		justify-items         :center;
		.cell{
			box-sizing      :border-box;
			margin          :0;
			padding         :5px;
			border          :1px solid rgba(239, 239, 245, 1);
			width           :100%;
			height          :100%;
			cursor          :pointer;
			display         :flex;
			flex-direction  :column;
			flex-wrap       :nowrap;
			align-content   :center;
			justify-content :center;
			align-items     :center;
			transition      :color .3s cubic-bezier(0.4, 0, 0.2, 1), border-color .3s cubic-bezier(0.4, 0, 0.2, 1), background-color .3s cubic-bezier(0.4, 0, 0.2, 1);
			&:hover{
				background :rgba(243, 243, 245, 1);
			}
			.today{
				box-sizing       :border-box;
				margin           :0;
				padding          :0;
				border           :none;
				width            :1.8em;
				height           :1.8em;
				color            :#FFFFFF;
				background-color :#18A058;
				border-radius    :50%;
				display          :flex;
				flex-direction   :row;
				flex-wrap        :nowrap;
				align-content    :center;
				justify-content  :center;
				align-items      :center;
			}
			.other-calendar{
				box-sizing      :border-box;
				margin          :0;
				padding         :0;
				border          :none;
				height          :100%;
				width           :100%;
				display         :flex;
				flex-direction  :row;
				flex-wrap       :nowrap;
				align-content   :center;
				justify-content :space-evenly;
				align-items     :center;
				text-align      :center;
			}
			.cell-bottom{
				border           :1.5px solid rgba(255, 255, 255, 0);;
				width            :100%;
				background-color :#0000;
				transition       :background-color .3s cubic-bezier(0.4, 0, 0.2, 1);
			}
		}
		.otherMonth{
			color :#C2C2C2;
		}
		.selected{
			background :rgb(243, 243, 245);
		}
		.cell + .cell{
			margin :0 -1px;
		}
		.cell.selected .cell-bottom{
			border :1.5px solid #18A058;
		}
	}
}
</style>